#include "TcpServer.hpp"
#include "Protocol.hpp"
#include "Daemon.hpp"
#include <memory>
#include <signal.h>

using namespace Tcpserver;
using namespace Protocol;

static void usage(const std::string &process)
{
    std::cout << std::endl
              << "Usage: " << process << " port" << std::endl
              << std::endl;
}

static Response calculate(const Request &req)
{
    Response resp(0, 0, req._left, req._right, req._op);
    switch (req._op)
    {
    case '+':
        resp._result = req._left + req._right;
        break;
    case '-':
        resp._result = req._left - req._right;
        break;
    case '*':
        resp._result = req._left * req._right;
        break;
    case '/':
        if (0 == req._right)
            resp._code = DIVZERO;
        else
            resp._result = req._left / req._right;
        break;
    case '%':
        if (0 == req._right)
            resp._code = MODZERO;
        else
            resp._result = req._left % req._right;
        break;
    default:
        resp._code = ILLEGAL;
        break;
    }
    return resp;
}

void calculateService(int serviceSocket)
{
    std::string inbuffer;
    while (true)
    {
        // 1. 读取客户端发的信息
        bool recvOk = Recv(serviceSocket, &inbuffer);
        if (!recvOk)
            break;

        // 2. 协议解析 得到一个完整的报文
        std::string package = Decode(inbuffer);
        if (package.empty())
            continue;

        logMsg(NORMAL, "package: %s", package.c_str());

        // 3. 反序列化 字节流 -> 结构化
        Request req;
        req.Deserialize(package);

        // 5. 业务逻辑
        Response resp = calculate(req);

        // 6. 对计算结果进行序列化
        std::string respString = resp.Serialize(); 
        
        // 7. 添加长度信息 "length\r\ncode result\r\n"
        respString = Encode(respString);

        Send(serviceSocket, respString);
    }
}

// ./CalServer port
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        usage(argv[0]);
        exit(1);
    }

    // server的编写要有较为严谨的判断逻辑
    // 一般服务器都要忽略SIGPIPE信号 防止在运行中出现非法写入导致服务端终止的问题
    // signal(SIGPIPE, SIG_IGN);

    //MyDaemon();
    std::unique_ptr<TcpServer> server(new TcpServer(atoi(argv[1])));

    server->AddService(calculateService);
    server->Start();

    return 0;
}
